package com.developer.platform.domain.scheduler;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONUtil;
import com.developer.platform.domain.NoticeAggregateRoot;
import com.developer.platform.domain.Systems;
import com.developer.platform.domain.User;
import com.developer.platform.domain.repository.INoticeRepository;
import com.developer.platform.domain.service.IQuartzJobService;
import com.developer.platform.infrastructure.SpringContext;
import com.developer.platform.infrastructure.client.DingDingClient;
import com.developer.platform.infrastructure.data.mapper.SystemMapper;
import com.developer.platform.infrastructure.data.mapper.UserMapper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import org.apache.commons.lang3.text.StrSubstitutor;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.stereotype.Component;

/**
 * 通知定时任务
 *
 * @author ：qiaoliang
 * @date ：2021-01-07
 */
@Component
public class NoticeSchedulerQuartzJob implements Job  {

  private final INoticeRepository noticeRepository;
  private final IQuartzJobService quartzJobService;
  private final DingDingClient dingDingClient;
  private final SystemMapper systemMapper;
  private final UserMapper userMapper;

  public NoticeSchedulerQuartzJob(
      INoticeRepository noticeRepository,
      IQuartzJobService quartzJobService,
      DingDingClient dingDingClient,
      SystemMapper systemMapper,
      UserMapper userMapper) {
    this.noticeRepository = noticeRepository;
    this.quartzJobService = quartzJobService;
    this.dingDingClient = dingDingClient;
    this.systemMapper = systemMapper;
    this.userMapper = userMapper;
  }

  @Override
  public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
    JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap();
    Object jobId = jobDataMap.get("id");
    if(Objects.isNull(jobId)){
      return;
    }
    long id = Long.parseLong((String)jobId);
    NoticeAggregateRoot noticeAggregateRoot = noticeRepository.findById(id);
    if(Objects.nonNull(noticeAggregateRoot)){
      List<Long> systemIds = Lists.newArrayList();
      if(CollUtil.isNotEmpty(noticeAggregateRoot.getInfluenceIds())){
        systemIds.addAll(noticeAggregateRoot.getInfluenceIds());
      }
      systemIds.addAll(noticeAggregateRoot.getSystemIds());
      List<Systems> systemsList = this.systemMap(systemIds);
      Map<Long, String> systemNameMap = this.systemNameMap(systemsList);
      List<Long> dingDingUser = Lists.newArrayList();
      dingDingUser.addAll(noticeAggregateRoot.getNoticeUserIds());
      if(CollUtil.isNotEmpty(noticeAggregateRoot.getDateUserIds())){
        dingDingUser.addAll(noticeAggregateRoot.getDateUserIds());
      }
      if(CollUtil.isNotEmpty(noticeAggregateRoot.getTellUserIds())){
        dingDingUser.addAll(noticeAggregateRoot.getTellUserIds());
      }
      dingDingUser.addAll(noticeAggregateRoot.getDurationUserIds());
      Map<Long, String> userNameMap = this.userPhoneMap(dingDingUser);

      Map<String, String> map = Maps.newHashMap();
      // 更新环境
      map.put("environment",(String) jobDataMap.get("templateName"));
      // 更新系统
      map.put("updateSystem",this.handle(noticeAggregateRoot.getSystemIds(), systemNameMap, true));
      // 更新内容
      map.put("content",this.handle(JSONUtil.toList(JSONUtil.parseArray(noticeAggregateRoot.getContents()), String.class)));
      // 风险等级
      map.put("risk",noticeAggregateRoot.getRiskName());
      // 受影响系统
      map.put("affectSystem",this.handle(noticeAggregateRoot.getInfluenceIds(), systemNameMap, true));
      // 更新方式
      map.put("mode",noticeAggregateRoot.getModeName());
      // 更新时间
      map.put("onlineTime",noticeAggregateRoot.getOnlineTimeName());
      // 更新时长
      map.put("duration",noticeAggregateRoot.getDurationName());
      // 更新人员
      map.put("updateUser",this.handle(noticeAggregateRoot.getDurationUserIds(), userNameMap, false));
      // 通知人员
      map.put("noticeUser",this.handle(noticeAggregateRoot.getNoticeUserIds(), userNameMap, false));
      // 反馈时间
      map.put("feedback",noticeAggregateRoot.getFeedbackName());
      // 详情连接
      map.put("url",this.handle(JSONUtil.toList(JSONUtil.parseArray(noticeAggregateRoot.getUrls()), String.class)));
      //数据库结构是否已变动
      map.put("dataChanged",noticeAggregateRoot.getDataChangedName());
      if(CollUtil.isNotEmpty(noticeAggregateRoot.getDateUserIds())){
        //数据库变动通知人员
        map.put("dateUser",this.handle(noticeAggregateRoot.getDateUserIds(), userNameMap, false));
      }
      //手机号通知人员
      map.put("tellUser",this.handle(noticeAggregateRoot.getTellUserIds(), userNameMap, false));
      StrSubstitutor strSubstitutor = new StrSubstitutor(map);
      String replace = strSubstitutor.replace(((String) jobDataMap.get("templateContent")).replace("\r",""));
      dingDingClient.send((String)jobDataMap.get("webhook"),
          (String)jobDataMap.get("sign"),replace,
          userNameMap.keySet().stream().map(
              userNameMap::get).collect(Collectors.toList()));
      systemsList.parallelStream().peek(systems -> {
        if(StrUtil.isNotBlank(systems.getTriggerUrl())){
          HttpRequest.get(systems.getTriggerUrl());
        }
      });
      quartzJobService.close((String)jobDataMap.get("jobName"), (String)jobDataMap.get("subgroup"));
    }
  }

  private String handle(List<Long> ids, Map<Long, String> map, boolean sort){
    StringBuilder name = new StringBuilder();
    if(CollUtil.isNotEmpty(ids)){
      for (int i = 0; i < ids.size(); i++) {
        if(sort){
          name.append("\b").append(i + 1).append(".").append(map.get(ids.get(i)));
          if(i < (ids.size()-1)){
            name.append("\n");
          }
        }else {
          name.append("@").append(map.get(ids.get(i)));
        }
      }
    }
    return name.toString();
  }

  private String handle(List<String> list){
    StringBuilder name = new StringBuilder();
    if(CollUtil.isNotEmpty(list)){
      for (int i = 0; i < list.size(); i++) {
        name.append("\b").append(i+1).append(".")
            .append(list.get(i));
        if(i < (list.size()-1)){
          name.append("\n");
        }
      }
    }
    return name.toString();
  }

  /**
   *  通过系统ID查询系统名称
   *
   * @author ：qiaoliang
   * @param ids : 系统id
   * @return java.util.Map<java.lang.String, java.lang.String>
   * @date 2020-11-12 14:12
   */
  public List<Systems> systemMap(List<Long> ids){
    if(CollUtil.isEmpty(ids)){
      return Lists.newArrayList();
    }
    return systemMapper.selectBatchIds(ids);
  }

  public Map<Long, String> systemNameMap(List<Systems> list){
    return list.stream().collect(Collectors.toMap(Systems::getId, Systems::getName));
  }

  /**
   *  通过用户ID查询用户手机号
   *
   * @author ：qiaoliang
   * @param ids : 用户id
   * @return java.util.Map<java.lang.String, java.lang.String>
   * @date 2020-11-12 14:12
   */
  public Map<Long, String> userPhoneMap(List<Long> ids){
    if(CollUtil.isEmpty(ids)){
      return Maps.newHashMap();
    }
    return userMapper.selectBatchIds(ids).stream()
        .collect(Collectors.toMap(User::getId, User::getPhone));
  }

}
